package cn.tedu.straw.api.service.impl;


import cn.tedu.straw.api.dto.PostQuestionDTO;
import cn.tedu.straw.api.ex.InsertException;
import cn.tedu.straw.api.ex.QuestionNotFoundException;
import cn.tedu.straw.api.mapper.QuestionMapper;
import cn.tedu.straw.api.mapper.QuestionTagMapper;
import cn.tedu.straw.api.mapper.UserQuestionMapper;
import cn.tedu.straw.api.service.IQuestionService;
import cn.tedu.straw.commons.model.Question;
import cn.tedu.straw.commons.model.QuestionTag;
import cn.tedu.straw.commons.model.UserQuestion;
import cn.tedu.straw.commons.vo.QuestionDetailVO;
import cn.tedu.straw.commons.vo.QuestionListItemVO;
import cn.tedu.straw.commons.vo.QuestionVO;
import cn.tedu.straw.commons.vo.TagVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author tedu.cn
 * @since 2020-08-11
 */
@Service
@Transactional
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {

    @Autowired
    private UserQuestionMapper userQuestionMapper;

    @Autowired
    private QuestionTagMapper questionTagMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Override
    public Integer postQuestion(PostQuestionDTO postQuestionDTO, Integer userId, String userNickName) {
        // 创建当前时间对象now
        LocalDateTime now = LocalDateTime.now();
        //处理标签id数据的字符串
        String tagIdsString = Arrays.toString(postQuestionDTO.getTagIds());
        tagIdsString = tagIdsString.substring(1, tagIdsString.length() - 1);
        // 创建Question对象
        Question question = new Question();
        // 向Question对象中封装数据：title > 从参数postQuestionDTO获取
        question.setTitle(postQuestionDTO.getTitle());
        // 向Question对象中封装数据：content > 从参数postQuestionDTO获取
        question.setContent(postQuestionDTO.getContent());
        // 向Question对象中封装数据：userNickName > 参数userNickname
        question.setUserNickName(userNickName);
        // 向Question对象中封装数据：userId > 参数userId
        question.setUserId(userId);
        // 向Question对象中封装数据：createdTime > now
        question.setCreatedTime(now);
        // 向Question对象中封装数据：status > 0
        question.setStatus(0);
        // 向Question对象中封装数据：hits > 0
        question.setHits(0);
        // 向Question对象中封装数据：isPublic > 1
        question.setIsPublic(1);
        // 向Question对象中封装数据：modifiedTime > now
        question.setModifiedTime(now);
        // 向Question对象中封装数据：isDelete > 0
        question.setIsDelete(0);
        // 向Question对象中封装数据：tagIds > 从参数postQuestionDTO获取，并转换为String
        question.setTagIds(tagIdsString);
        // 调用questionMapper.insert(Question question)方法向question表中插入数据，并获取返回值
        int rows = questionMapper.insert(question);
        // 判断返回值是否不为1
        if (rows != 1) {
            // 是：抛出InsertException
            throw new InsertException("发布问题失败，服务器异常，请稍后再试！");
        }


        // 遍历参数postQuestionDTO中的tagIds
        for (Integer tagId : postQuestionDTO.getTagIds()) {
            // -- 创建QuestionTag对象
            QuestionTag questionTag = new QuestionTag();
            // -- 向QuestionTag对象中封装数据：questionId > 从以上插入成功的Question对象中获取
            questionTag.setQuestionId(question.getId());
            // -- 向QuestionTag对象中封装数据：tagId > 被遍历到的数组元素
            questionTag.setTagId(tagId);
            // -- 调用questionTagMapper.insert(QuestionTag questionTag)向question_tag表中插入数据，并获取返回值
            rows = questionTagMapper.insert(questionTag);
            // -- 判断返回值是否不为1
            if (rows != 1) {
                // -- 是：抛出InsertException
                throw new InsertException("发布问题失败，服务器异常，请稍后再试！");
            }
        }

        // 遍历postQuestionDTO中的teacherIds
        for (Integer teacherId : postQuestionDTO.getTeacherIds()) {
            // -- 创建UserQuestion对象
            UserQuestion userQuestion = new UserQuestion();
            // -- 向UserQuestion对象中封装数据：questionId > 从以上插入成功的Question对象中获取
            userQuestion.setQuestionId(question.getId());
            // -- 向UserQuestion对象中封装数据：userId > 被遍历到的数组元素
            userQuestion.setUserId(teacherId);
            // -- 向UserQuestion对象中封装数据：createdTime > now
            userQuestion.setCreatedTime(now);
            // -- 调用userQuestionMapper.insert(UserQuestion userQuestion)向user_question表中插入数据，并获取返回值
            rows = userQuestionMapper.insert(userQuestion);
            // -- 判断返回值是否不为1
            if (rows != 1) {
                // -- 是：抛出InsertException
                throw new InsertException("发布问题失败，服务器异常，请稍后再试！");
            }
        }

        // 返回Question对象中的id
        return question.getId();
    }

    @Override
    public List<QuestionListItemVO> getQuestionList() {
        return questionMapper.findHitList();
    }


    @Autowired
    private RestTemplate restTemplate;

    @Value("${project.questions.my-list.page-size}")
    private Integer pageSize;

    @Override
    public PageInfo<QuestionVO> getMyQuestions(Integer userId, Integer page) {
        // 设置页面参数
        PageHelper.startPage(page, pageSize);
        // 获取当前用户id的问题列表
        List<QuestionVO> questions = questionMapper.findMyQuestions(userId);

        // 遍历查询到的问题列表，将数据封装到响应的对象中
        for (QuestionVO question : questions) {
            // 从查询结果中获取当前问题标签的id值
            String tagIdsStr = question.getTagIds();
            // 将问题标签的id拆分放入字符串数组中
            String[] tagIdArray = tagIdsStr.split(", ");
            // 准备标签数据集合
            List<TagVO> tags = new ArrayList<>();
            // 遍历问题标签数组id,逐一获取数据
            for (int i = 0; i < tagIdArray.length; i++) {
                // 设置Ribbon请求的URL
                // 以下URL中 在本应该写主机名、端口号的位置，需要改为提供者在Eureka Server客户端的名称
                // URL中的{1}代表第一个参数占位符(可以填写多个占位符)
                String url = "http://redis-tag/v1/tags/{1}/simple";

                // 获取Ribbon响应回来的数据
                // 在getForObject中有三个参数分别为：
                /**
                 * 1.url:消费者向提供者发起请求的请求路径
                 * 2.responseType:提供者向消费者返回数据的数据类型
                 * 3.消费者请求的URL中的参数占位符的具体参数(如有多个需要填写多个参数)
                 */
                TagVO tag = restTemplate.getForObject(url, TagVO.class, tagIdArray[i]);
                // 将通过远程服务获取的数据保存到集合中
                tags.add(tag);
            }
            question.setTags(tags);
        }
        // 创建PageInfo对象，并将集合数据封装到PageInfo中
        PageInfo<QuestionVO> questionVOPageInfo = new PageInfo<>(questions);
        return questionVOPageInfo;
    }


    @Override
    public QuestionDetailVO getQuestionDetail(Integer id) {

        QuestionDetailVO questionDetailVO = questionMapper.findById(id);
        if (questionDetailVO == null) {
            throw new QuestionNotFoundException("查询详情问题失败！尝试访问的数据不存在。");
        }
        // 从查询结果中获取当前问题标签的id值
        String tagIdsStr = questionDetailVO.getTagIds();
        // 将问题标签的id拆分放入字符串数组中
        String[] tagIdArray = tagIdsStr.split(", ");
        // 准备标签数据集合
        List<TagVO> tags = new ArrayList<>();
        // 设置Ribbon请求的URL
        // 以下URL中 在本应该写主机名、端口号的位置，需要改为提供者在Eureka Server客户端的名称
        // URL中的{1}代表第一个参数占位符(可以填写多个占位符)
        String url = "http://redis-tag/v1/tags/{1}/simple";
        // 遍历问题标签数组id,逐一获取数据
        for (int i = 0; i < tagIdArray.length; i++) {

            // 获取Ribbon响应回来的数据
            // 在getForObject中有三个参数分别为：
            /**
             * 1.url:消费者向提供者发起请求的请求路径
             * 2.responseType:提供者向消费者返回数据的数据类型
             * 3.消费者请求的URL中的参数占位符的具体参数(如有多个需要填写多个参数)
             */
            TagVO tag = restTemplate.getForObject(url, TagVO.class, tagIdArray[i]);
            // 将通过远程服务获取的数据保存到集合中
            tags.add(tag);
        }
        questionDetailVO.setTags(tags);
        return questionDetailVO;
    }
}
